/*******************************************************************************
 *
 * Advanced Distributed Learning (ADL) Technology Center grants you ("Licensee")
 * a non-exclusive, royalty free, license to use, modify and redistribute this
 * software in source and binary code form, provided that i) this copyright
 * notice and license appear on all copies of the software; and ii) Licensee
 * does not utilize the software in a manner which is disparaging to the ADL
 * Technology Center. iii) Any Modifications to the file are described in plain
 * language following this license.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
 * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. The ADL TECHNOLOGY CENTER AND ITS
 * LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A
 * RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES.
 * IN NO EVENT WILL THE ADL TECHNOLOGY CENTER OR ITS LICENSORS BE LIABLE FOR ANY
 * LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS
 * OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE
 * SOFTWARE, EVEN IF ADL Technology Center HAS BEEN ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGES.
 *
 * This Software has been developed by Concurrent Technologies Corporation (CTC)
 * under contract NBCHD020024 for the U.S. Government.
 *
 ******************************************************************************/
package org.adl.registry.website.rim;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;

/**
 * 
 * <strong>Filename: </strong> RegistryProxy.java <br />
 * <strong>Description: </strong> <br />
 * The ADL Registry contains a http post interface behind a layer of user
 * authorization. Data is sent as properties or files over the stream.
 * PortalPost contains methods for executing a post against the ADL Registry web
 * site. <br />
 * <br />
 * 
 * <strong>Design Issues: </strong>To Be Determined <br />
 * <br />
 * 
 * <strong>Implementation Issues: </strong>To Be Determined <br />
 * <br />
 * 
 * <strong>Known Problems: </strong>To Be Determined <br />
 * <br />
 * 
 * <strong>Side Effects: </strong>To Be Determined <br />
 * <br />
 * 
 * <strong>References: </strong>
 * <ul>
 * <li>ADL-R Reg-T IM and XSD</li>
 * <li>ADL-R Reg-TS IM and XSD</li>
 * </ul>
 * @author ADL Technical Team
 */
public class RimProxy
{
    /**
     * The Boundry
     */
    protected static final String SECTION_GUID = "---B6FF08DEDA06---";
    
    /**
     * When doing stream copies, the buffer size to use
     */
    private static final int BUFFER_SIZE = 32768;
    
    /**
     * The time in miliseconds that the Test Harness will wait for a response
     * from the registry before timing out.
     */
    private static final int TIMEOUT = 10000;
    
    /**
     * The encoding to use.
     */
    private static final String ENCODING = "UTF-8";
    
    /**
     * The portal URL address string
     */
    protected String mPortalURL = "";
    
    /**
     * The connection to the URL.
     */
    protected URLConnection mConnection = null;
    
    /**
     * The stream over the current connection.
     */
    protected OutputStreamWriter mPostStream = null;
    
    /**
     * Creates a new instance of RegistryProxy with the specificified RIM url.
     * @param iRimURL The url loaction of the RIM interface.
     */
    public RimProxy(String iRimURL)
    {
        this.mPortalURL = iRimURL;
    }
    
    /**
     * Sets the URL of the RIM interface.
     * @param url The <CODE>String</CODE> url location of the RIM interface.
     */
    public void setRimURL(String url)
    {
        this.mPortalURL = url;
    }
    
    /**
     * Closes the underlying resources.
     *
     * @throws IOException
     *            when the close fails
     */
    public void close() throws IOException
    {
        if (mPostStream != null)
        {
            mPostStream.close();
        }
    }
    
    /**
     * Opens a connection.
     *
     * @throws IOException
     *            If there was an error with the output streams.
     */
    public void openConnection() throws IOException
    {
        try
        {
            URL registry = new URL(mPortalURL);
            mConnection = registry.openConnection();
            mConnection.setDoOutput(true);
            mConnection.setDoInput(true);
            mConnection.setUseCaches(false);
            mConnection.setConnectTimeout(TIMEOUT);
            mConnection.setReadTimeout(TIMEOUT);
            
            mConnection.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            mPostStream = new OutputStreamWriter(mConnection.getOutputStream(),
                    ENCODING);
        }
        catch (SocketTimeoutException s)
        {
            throw s;
        }
    }
    
    /**
     * Forwards a multipart post to a servlet on a different server.
     *
     * @param iStream
     *           the stream from the servlet
     * @throws IOException
     *            on an error
     */
    public void forwardMultipart(InputStream iStream) throws IOException
    {
        URL registry = new URL(mPortalURL);
        mConnection = registry.openConnection();
        mConnection.setDoOutput(true);
        mConnection.setDoInput(true);
        mConnection.setUseCaches(false);
        
        // set URLConnection properties
        mConnection.setRequestProperty("Content-type",
                "multipart/form-data; boundary=" + SECTION_GUID);
        mConnection.setRequestProperty("Referer", "http://127.0.0.1");
        mConnection.setRequestProperty("Cache-Control", "no-cache");
        
        mPostStream = new OutputStreamWriter(mConnection.getOutputStream(),
                ENCODING);
        InputStreamReader in = new InputStreamReader(iStream, ENCODING);
        
        int buffer = 0;
        while ((buffer = in.read()) != -1)
        {
            mPostStream.write(buffer);
        }
        in.close();
    }
    
    /**
     * Writes a value to the open connection.
     *
     * @param iParam
     *           the parameter to write.
     *
     * @param iValue
     *           the value to write.
     *
     * @throws IOException
     *            when the write fails.
     */
    public void writeParam(String iParam, String iValue) throws IOException
    {
        String request = iParam + "=" + iValue + "&";
        mPostStream.write(request);
    }
    
    /**
     * Writes the response to a string
     *
     * @return the response as a string
     *
     * @throws IOException
     *            on error
     */
    public String writeResponseTo() throws IOException
    {
        StringBuffer returnValue = new StringBuffer();
        mPostStream.flush();
        mPostStream.close();
        
        InputStreamReader in = new InputStreamReader(
                mConnection.getInputStream(), ENCODING);
        
        char buf[] = new char[BUFFER_SIZE];
        
        int i;
        while ((i = in.read(buf)) != -1)
        {
            returnValue.append(new String(buf, 0, i));
        }
        
        in.close();
        
        return returnValue.toString();
    }
}